using System.Collections;
using Framework;
using Framework.Core;
using IngameDebugConsole;
using UnityEngine;

public class GameEntry
{
    private static GameObject _inner;
    private static string _json;
    private static GameObject _coreGo;
    private static FrameworkCore _core;
    public static Timer Timer { get; private set; }
    public static CoroutineManager Coroutine { get; private set; }
    private static AssetLoader Loader;
    public static ResLoader AssetsLoader { get; private set; }
    public static AtlasLoader Atlas { get; private set; }
    public static UGUIManager GUI { get; private set; }
    public static TableManager Table { get; private set; }
    public static AudioManager Audio { get; private set; }
    public static GUIPathInfo GUIPath { get; private set; }
    public static GameProcedureManager GameProcedure { get; private set; }
    public static EntityManager Entity { get; private set; }
    public static GameContext Context { get; private set; }
    public static Logger Log { get; private set; }
    private static UIBackFeature _uibackFeature;
    public static InputDeviceManager DeviceManager { get; private set; }
    public static HttpManager HttpManager { get; private set; }
    private static string _editorRemoteLoadPath;


    public static void Startup(GameObject inner, string json)
    {
        if (_core != null) return;
        _inner = inner;
        DeviceManager = new InputDeviceManager();
        //Application.targetFrameRate = 60;
        _json = json;
        Log = new Logger();
        _coreGo = new GameObject("core");
        GameObject.DontDestroyOnLoad(_coreGo);
        _core = new FrameworkCore(_coreGo);
        Timer = _core.Timer;
        Coroutine = _core.Coroutine;
        GUIPath = new GUIPathInfo();
        Table = new TableManager();
        HttpManager=new HttpManager();
        HttpManager.SetCoroutineManager(Coroutine);
        bool editorMode = false;
#if UNITY_EDITOR
        _editorRemoteLoadPath = PlayerPrefs.GetString("RemoteLoadPath");
        editorMode = true;
#else
        
#endif
        if (editorMode && string.IsNullOrEmpty(_editorRemoteLoadPath))
        {
            var editorLoader = new EditorAssetLoader();
            editorLoader.Initialize(0.1f);
            Loader = editorLoader;
            AssetsLoader = new ResLoader(Loader);
            _core.Coroutine.Start(initEnv(), "initEnv");
        }
        else
        {
            _core.Coroutine.Start(initBundleAssetLoader(), "initBundleAssetLoader");
        }

    }

    private static IEnumerator initBundleAssetLoader()
    {
        //请求服务器返回一些信息
        // 或者从热更代码那里带回信息

        //最新的资源版本号
        var versionFromServer = "abbeab905ab0a5e498c37ef40d2e2b68";
        //远程资源地址
        var updateURLFromServer = "http://127.0.0.1/bundles/";
        updateURLFromServer = "";
        //是否开启更新模式
        var updateEnable = true;
        var versionFile = "AssetBundles/version.bytes";
        var downloader = new BundleDownload(_core.Coroutine);
        if (!updateEnable)
        {
            updateURLFromServer = string.Empty;
        }
#if UNITY_EDITOR
        if (!string.IsNullOrEmpty(_editorRemoteLoadPath))
        {
            // downloader.SetDownloadSpeed(1024 * 1024 * 5);//模拟下载速度
            updateURLFromServer = _editorRemoteLoadPath;
        }
#endif
        //Debug.LogErrorFormat("资源远程下载地址{0}",updateURLFromServer);
        yield return downloader.Initialize(updateURLFromServer, versionFile, versionFromServer);
        if (!downloader.Enabled)
        {
            yield break;
        }
        //请求更新资源
        yield return downloader.Request();
        if (!downloader.RequestFinished)
        {
            Debug.Log("网络请求失败");
            yield break;
        }
        bool downloadNow = true;
        if (downloadNow)
        {
            // 统计并下载文件
            var count = downloader.NeedUpdateFileCount;
            while (downloader.NeedUpdateFileCount > 0)
            {
                var file = downloader.ReadUpdateFile();
                downloader.Download(file);
            }
            //已下载个数
            int loadedCount = 0;
            while (loadedCount < count)
            {
                var c = downloader.LoadSuccessFiles.Count;
                while (c-- > 0)
                {
                    var file = downloader.LoadSuccessFiles.Dequeue();
                    loadedCount++;
                    Debug.LogFormat("{0}/{1}", loadedCount, count);
                }
                yield return null;
            }
            if (downloader.LoadErrorFiles.Count > 0)
            {
                Debug.Log("文件下载存在失败的条目");
                //重新执行一次当前方法
                yield break;
            }
        }
        if (Loader == null)
        {
            var bundleLoader = new BundleAssetLoader();
            bundleLoader.Initialize(versionFile, _core.Coroutine, downloader);
            bundleLoader.SetUnloadDelayTime(3f);
            bundleLoader.SetAssetProcessor(new AssetProcessor());
            Loader = bundleLoader;
            AssetsLoader = new ResLoader(Loader);
        }
        _core.Coroutine.Start(initEnv(), "initEnv");
    }
    private static IEnumerator initEnv()
    {
        Context = new GameContext();
        _core.OnUpdate = onUpdate;
        Atlas = new AtlasLoader(Loader);
        var loadAsset = AssetsLoader.LoadAsset("Assets/Res/Prefabs/Entry.prefab");
        yield return loadAsset;
        if (!(loadAsset.Asset is GameObject go))
        {
            yield break;
        }
        /*
        var debug = GameObject.Find("[Debug Updater]");
        if (debug != null)
        {
            debug.SetActive(false);
            var complist = debug.GetComponents<Component>();
            foreach (var item in complist)
            {
                if (item is MonoBehaviour behaviour)
                {
                    behaviour.enabled = false;
                }
            }
            GameObject.DestroyImmediate(debug);
        }
        */
        GameObject entry = go;
        GameObject.DontDestroyOnLoad(entry);
        _coreGo.transform.SetParent(entry.transform);
        _coreGo.transform.SetAsFirstSibling();
        var gameConfig = entry.GetComponent<GameConfig>();
        GameEntry.Context.GameConfig = gameConfig;
        _uibackFeature = new UIBackFeature();
        var uiconfig = entry.GetComponent<GUIConfig>();
        if (uiconfig != null)
        {
            GUI = new UGUIManager();
            GUI.Initialize(uiconfig);
            GUI.Initialize(Loader);
            //安全区域修改器
            GUI.SetModifier(new SafeAreaModifier(uiconfig));
            GUI.AddFeature(_uibackFeature);
        }
        var audioConfig = entry.GetComponent<AudioConfig>();

        if (audioConfig != null)
        {
            Audio = new AudioManager(Loader);
            Audio.Initialize(audioConfig.Mixer, audioConfig.Parent, new string[] { "Master", "Master/Music" });
        }
        Entity = new EntityManager(gameConfig.EneityContainer, Loader);
        loadAsset = AssetsLoader.LoadAsset("Assets/Res/Fsm/GameProcedure.asset");
        yield return loadAsset;
        if (loadAsset.Asset is FsmData fsmData)
        {
            GameProcedure = new GameProcedureManager(fsmData.GetFsm());
        }
        AssetsLoader.Unload(loadAsset);
        QualitySettings.vSyncCount = 0;
        yield return new WaitForSeconds(1f);
        _inner?.SetActive(false);
    }

    private static void onUpdate(float deltaTime, float unscaledDeltaTime)
    {
        AssetsLoader?.Update(deltaTime, unscaledDeltaTime);
        // Loader?.Update(deltaTime, unscaledDeltaTime);
        Atlas?.Update(deltaTime, unscaledDeltaTime);
        GUI?.Update(deltaTime, unscaledDeltaTime);
        Context?.Update(deltaTime, unscaledDeltaTime);
        Entity?.Update(deltaTime, unscaledDeltaTime);
        GameProcedure?.Update(deltaTime, unscaledDeltaTime);
        _uibackFeature?.Update();
        Log?.Update();
        DeviceManager.Update(unscaledDeltaTime);
        HttpManager?.Update(deltaTime, unscaledDeltaTime);

        if (Input.GetMouseButtonDown(0))
        {
            if (Input.mousePosition.x > 0.8f * Screen.width && Input.mousePosition.y > 0.8f * Screen.height)
            {
                debugCount++;
                if (debugCount > 8)
                {
                    DebugLogManager.Instance.PopupEnabled = true;
                }
            }
            else
            {
                debugCount = 0;
            }
        }
    }
    private static int debugCount = 0;
}
public class Logger
{
    private static Framework.ILogger logger = new DebugLogger();
    public void SetLogger(Framework.ILogger logger)
    {
        Logger.logger = logger;
    }
    [System.Diagnostics.Conditional("LogError")]
    public void LogErrorFormat(string format, params object[] args)
    {
        logger?.LogErrorFormat(format, args);
    }
    [System.Diagnostics.Conditional("LogError")]
    public void LogError(object message)
    {
        logger?.LogError(message);
    }
    [System.Diagnostics.Conditional("Log")]
    public void LogFormat(string format, params object[] args)
    {
        logger?.LogFormat(format, args);
    }
    [System.Diagnostics.Conditional("Log")]
    public void Log(object message)
    {
        logger?.Log(message);
    }
    [System.Diagnostics.Conditional("LogWarning")]
    public void LogWarning(object message)
    {
        logger?.LogWarning(message);
    }
    [System.Diagnostics.Conditional("LogWarning")]
    public void LogWarningFormat(string format, params object[] args)
    {
        logger?.LogWarningFormat(format, args);
    }
    public void Update()
    {
        logger?.Update();
    }
}